package com.dxy.hms.utils;

import cn.hutool.core.util.StrUtil;
import com.dxy.hms.auth.LoginUser;
import com.dxy.hms.auth.UserContextHolder;
import com.dxy.hms.base.StatusMessageEnum;
import com.dxy.hms.base.UnifiedException;
import com.dxy.hms.cache.ExpiringCache;
import com.dxy.hms.cache.ICache;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class LoginUtil {


    // token标识
    public static final String TOKEN_KEY = "x-auth-token";
    // 模式
    private static String mode;

    @Value("${mode:}")
    public void setMode(String mode) {
        LoginUtil.mode = mode;
    }

    // 登录状态缓存，退出登录时标记为下线状态，解决jwt滥用问题（jwt是无状态的，一经签发就不能更改）
    // private static final LoadingCache<String, Optional<Boolean>> LOGIN_STATUS_CACHE = CacheBuilder.newBuilder()
    //         .initialCapacity(100) // 初始容量为10
    //         .maximumSize(10000) // 缓存大小
    //         .concurrencyLevel(20) // 并发级别为20
    //         .expireAfterWrite(JwtUtil.expire, TimeUnit.MINUTES) // 写缓存后过期时间
    //         //设置缓存的移除通知
    //         .removalListener(notification -> log.debug("login_status_cache: {} was removed, cause is {}", notification.getKey(), notification.getCause()))
    //         //build方法中可以指定CacheLoader，在缓存不存在时通过CacheLoader的实现自动加载缓存
    //         .build(new CacheLoader<String, Optional<Boolean>>() {
    //             @Override
    //             public Optional<Boolean> load(String jti) throws Exception {
    //                 // 当获取key的缓存不存在时，不需要自动添加
    //                 return Optional.empty();
    //             }
    //         });

    private static final ICache<String, Boolean> LOGIN_STATUS_CACHE;

    static {
        LOGIN_STATUS_CACHE = new ExpiringCache<String, Boolean>()
                .setDuration(JwtUtil.expire)
                .setTimeUnit(TimeUnit.MINUTES);
    }

    public static String getToken() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        return getToken(request);
    }

    public static String getToken(HttpServletRequest request) {
        // 1. 从cookie中获取
        Cookie[] cookies = request.getCookies();
        if (cookies != null && cookies.length > 0) {
            for (Cookie cookie : cookies) {
                if (TOKEN_KEY.equals(cookie.getName())) {
                    return cookie.getValue();
                }
            }
        }

        // 2. 从header中获取
        String token = request.getHeader(TOKEN_KEY);
        if (StrUtil.isNotEmpty(token)){
            return token;
        }

        // 3. 从url中获取
        return request.getParameter("token");
    }

    public static LoginUser getLoginUser() {
        return UserContextHolder.get();
    }

    public static LoginUser getLoginUserOrException() {
        LoginUser loginUser = getLoginUser();
        if (loginUser == null) {
            throw new UnifiedException(StatusMessageEnum.UN_LOGIN);
        }
        return loginUser;
    }

    @SneakyThrows
    public static boolean checkLogin(String token) {
        if ("dev".equals(mode)){
            return true;
        }
        if (StrUtil.isNotEmpty(token)) {
            String jti = JwtUtil.getId(token);
            Boolean loginFlag = LOGIN_STATUS_CACHE.get(jti);
            return loginFlag != null && loginFlag;
        }
        return false;
    }

    public static void setOnline(String token) {
        LOGIN_STATUS_CACHE.put(JwtUtil.getId(token), Boolean.TRUE);
    }

    public static void setOffline(String token) {
        LOGIN_STATUS_CACHE.remove(JwtUtil.getId(token));
    }


}
